package ij.hkust.QuickPALM;

import ij.*;
import ij.IJ.*;
import ij.measure.*;
import ij.plugin.*;
import ij.plugin.filter.*;
import ij.plugin.frame.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.CurveFitter.*;
import java.awt.*;
import java.lang.Math;

import java.util.Random;

/**
 * 
 * @author linshan
 *
 */
public class Drawer implements PlugIn
{
	ImagePlus imp;
	ImageProcessor ip;
	ImageStack res;

	Random rd = new Random();
  
	MyDialogs dg = new MyDialogs();
  
	public void run(String args)
	{
		IJ.register(Drawer.class);
		if (!dg.drawer())
			return;
    
		int width = dg.drawer_owidth;
		int height = dg.drawer_oheight;

		double prob[][] = new double[width][height];

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < width; j++)
			{
				prob[i][j] = rd.nextDouble();
			}
		}

		ImageStack res = new ImageStack(width, height);

		for (int index = 0; index < dg.drawer_nframe; index++)
		{
		  ip = new ShortProcessor(width, height);
      for (int i = 0; i < width; i++)
		  {
			  for (int j = 0; j < height; j++)
			  {
          ip.set(i, j, (int) (2 * Math.sqrt(dg.drawer_max) * dg.drawer_noise * rd.nextDouble()));
	  		}
	  	}

			for (int m = 0; m < width; m++)
			{
				for (int n = 0; n < height; n++)
				{
					if (rd.nextDouble() < prob[m][n] * dg.drawer_intensity)
						DrawSpot(ip, m, n, width, height);
				}
			}

			res.addSlice(index + "", ip, 0);
		}
		
		imp = new ImagePlus("Sample file", res);
		imp.show();
	}

	void DrawSpot(ImageProcessor ip, int x, int y, int width, int height)
	{
		int peak = (int)(dg.drawer_max - dg.drawer_peakdev * rd.nextDouble());
		if (peak < 0)
			peak = 0;
				
		int xstart;
		int ystart;
		int xend;
		int yend;
   
		double radius = dg.drawer_radius * (0.9 + 0.2 * rd.nextDouble());

		if (dg.drawer_mode == dg.drawer_modes[0])
		{
      xstart = (x - (int)(1.5*radius) > 0)?(x - (int)(1.5*radius)):0;
      ystart = (y - (int)(1.5*radius) > 0)?(y - (int)(1.5*radius)):0;
      xend = (x + (int)(1.5*radius) < width)?(x + (int)(1.5*radius)):width - 1;
      yend = (y + (int)(1.5*radius) < height)?(y + (int)(1.5*radius)):height - 1;

			for (int i = xstart; i <= xend; i++)
			{
				for (int j = ystart; j <= yend; j++)
				{
					int old = ip.get(i, j);
					double r = Math.hypot(i - x, j - y);
					int add = (int)(peak*Math.exp(-2*r*r/(radius*radius)));
					ip.set(i, j, old + add);
				}
			}

		}

		/*else if (dg.drawer_mode == dg.drawer_modes[1])
		{
			double xdev;
			double ydev;
			int bound;
			
			xdev = dg.drawer_radius*(0.7+0.6*rd.nextDouble())/2;
//			if (xdev > dg.drawer_radius/2) //
			  ydev = (dg.drawer_radius/2)*(dg.drawer_radius/2)/xdev;
//			else
//			  ydev = (int)(dg.drawer_radius-xdev);
			   
			xstart = (int)((x-3*xdev>0)?(x-3*xdev):0);
  		ystart = (int)((y-3*ydev>0)?(y-3*ydev):0);
  		xend = (int)((x+3*xdev<width)?(x+3*xdev):(width-1));
  		yend = (int)((y+3*ydev<height)?(y+3*ydev):(height-1));

	  	for (int m = xstart; m <= xend; m++)
  		{
	  		for (int n = ystart; n <= yend; n++)
		  	{
			  	int old = ip.get(m, n);
					int dx = Math.abs(m - x);
					int dy = Math.abs(n - y);

					old += (int)(peak*Math.exp(-dx*dx/(2*xdev*xdev)-dy*dy/(2*ydev*ydev)));

  				ip.set(m, n, old);
  			}
			}
		}
		
		/* Drawing random spot mode
		else if (dg.drawer_mode == dg.drawer_modes[2])
		{
			int xdevl = (int)(dg.drawer_radius*(0.8 + 0.4*rd.nextDouble())/2);
			int xdevr = (int)(dg.drawer_radius*(0.8 + 0.4*rd.nextDouble())/2);
			int ydevl = (int)((2*dg.drawer_radius*dg.drawer_radius/((xdevr+xdevl)*(xdevr+xdevl))*(0.8 + 0.4*rd.nextDouble()))/2);
			int ydevr = (int)((2*dg.drawer_radius*dg.drawer_radius/((xdevr+xdevl)*(xdevr+xdevl))*(0.8 + 0.4*rd.nextDouble()))/2);
			   
			xstart = (x-2*xdevl>0)?(x-2*xdevl):0;
			ystart = (y-2*ydevl>0)?(y-2*ydevl):0;
  		xend = (x+2*xdevr<width)?(x+2*xdevr):(width-1);
  		yend = (y+2*ydevr<height)?(y+2*ydevr):(height-1);

			for (int m = xstart; m <= xend; m++)
  		{
		 		for (int n = ystart; n <= yend; n++)
		  	{
			  	int old = ip.get(m, n);
					int dx = Math.abs(m - x);
					int dy = Math.abs(n - y);
					int xdev;
					int ydev;

					if (m > x)
						xdev = xdevr;
					else
						xdev = xdevl;

					if (n > y)
						ydev = ydevr;
					else
						ydev = ydevl;

					old += (int)(peak*Math.exp(-dx*dx/(2*xdev*xdev)-dy*dy/(2*ydev*ydev)));

  				ip.set(m, n, old);
				}
			}
		}*/

	}
}


